using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Core.Base.UI;
using Core.Extension;
using Core.Mgr;
using Core.Mgr._ResMgr;
using Core.Mgr._Timer;
using DG.Tweening;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;

namespace Core.Mgrs
{
    public class UIMgr : SingletonMono<UIMgr>
    {
        public Camera uiCamera;
        public GameObject objRayMask;
        public Dictionary<EUIType, RectTransform> uiCanvasDic { get; } = new();

        public Dictionary<EUIType, RectTransform> uiCanvasDic_Height { get; } = new();

        private Dictionary<Type, BaseUI> uiDic = new();
        private List<Type> loadingUIList = new();

        /// 已经中断的用户界面
        private List<Type> _interruptedUI = new();

        public Vector2 CanvasSize => uiCanvasDic[EUIType.BaseCanvas].rect.size;

        /// <summary>
        /// 添加摄象机和画布
        /// </summary>
        public void OnInit()
        {
            uiCamera = transform.GetCom<Camera>("UICamera");
            uiCanvasDic.Add(EUIType.BaseCanvas, transform.GetCom<RectTransform>("BaseCanvas"));
            uiCanvasDic.Add(EUIType.MiddleCanvas, transform.GetCom<RectTransform>("MiddleCanvas"));
            uiCanvasDic.Add(EUIType.TopCanvas, transform.GetCom<RectTransform>("TopCanvas"));
            uiCanvasDic.Add(EUIType.TipsCanvas, transform.GetCom<RectTransform>("TipsCanvas"));
            uiCanvasDic_Height.Add(EUIType.BaseCanvas, transform.GetCom<RectTransform>("BaseCanvas_Height"));
            uiCanvasDic_Height.Add(EUIType.MiddleCanvas, transform.GetCom<RectTransform>("MiddleCanvas_Height"));
            uiCanvasDic_Height.Add(EUIType.TopCanvas, transform.GetCom<RectTransform>("TopCanvas_Height"));
            uiCanvasDic_Height.Add(EUIType.TipsCanvas, transform.GetCom<RectTransform>("TipsCanvas_Height"));
            DontDestroyOnLoad(this);
        }

        /// <summary>
        /// 打开指定UI
        /// </summary>
        /// <param name="tuple"></param>
        /// <param name="openedCb">成功打开后的回调</param>
        /// <param name="initedCb">初始化完成的回调</param>
        /// <typeparam name="T">想要打开的UI</typeparam>
        public void OnOpen<T>(ITuple tuple = null, Action<T> openedCb = null, Action<T> initedCb = null)
            where T : BaseUI
        {
            Type type = typeof(T);
            var uiAttribute = type.GetCustomAttribute(typeof(UIAttribute), false) as UIAttribute;
            if (uiDic.ContainsKey(type))
            {
                initedCb?.Invoke((T) uiDic[type]);
                uiDic[type].OnOpen(tuple);
                openedCb?.Invoke((T) uiDic[type]);
            }
            else
            {
                if (loadingUIList.Contains(type)) return;
                loadingUIList.Add(type);
                // 清空关闭指令
                ResMgr.LoadAsync($"UI/{uiAttribute.UIPath}.prefab",
                    delegate(GameObject prefab, AsyncOperationHandle<GameObject> handle)
                    {
                        if (_interruptedUI.Contains(type))
                        {
                            // 当前UI的打开进程被中断了(因为UI的开启进程是异步的，当前UI还没有成功开启，但是又发来了一个关闭指令)
                            _interruptedUI.Remove(type);
                            Addressables.Release(handle);
                            return;
                        }

                        var parent = uiAttribute.MatchMode == EScreenMatchMode.Width
                            ? uiCanvasDic[uiAttribute.UIType].transform
                            : uiCanvasDic_Height[uiAttribute.UIType].transform;
                        var baseUI = Instantiate(prefab.gameObject, parent).GetComponent<BaseUI>();
                        uiDic.Add(type, baseUI);
                        baseUI.aaHandle = handle;
                        baseUI.OnInit(uiAttribute);
                        initedCb?.Invoke((T) baseUI);
                        baseUI.OnOpen(tuple);
                        openedCb?.Invoke((T) baseUI);
                        loadingUIList.Remove(type);
                    });
            }
        }

        /// <summary>
        /// 关闭指定UI，如果UI正在加载中，则会中断。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void OnClose<T>() where T : BaseUI
        {
            Type type = typeof(T);
            if (uiDic.TryGetValue(type, out BaseUI baseUI))
            {
                if (baseUI.gameObject.activeSelf)
                {
                    baseUI.OnClose();
                }
            }
            else
            {
                if (loadingUIList.Contains(type))
                {
                    _interruptedUI.Add(type);
                    loadingUIList.Remove(type);
                }
            }
        }


        /// <summary>
        /// 获取当前内存中的UI，若没有则返回Null
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T GetUI<T>() where T : BaseUI
        {
            Type type = typeof(T);
            if (uiDic.TryGetValue(type, out BaseUI baseUI))
            {
                return baseUI as T;
            }

            return null;
        }

        public void MemoryListRemoveItem(BaseUI baseUI)
        {
            var type = baseUI.GetType();
            uiDic.Remove(type);
        }

        /// 黑色遮罩，位于所有UI的最顶层
        public Canvas canvasBlackMask;

        /// 设置UI对象为最高层，且是唯一可操作的对象。适用于新手引导
        public void StartGuide(GameObject guideObj, float shadowAnimDuration = 2)
        {
            var transGuideHand = canvasBlackMask.transform.Find("GuideHand").GetComponent<RectTransform>();
            transGuideHand.gameObject.SetActive(false);
            canvasBlackMask.gameObject.SetActive(true);
            // 获取到对象的视图坐标位置
            var pos = uiCamera.WorldToViewportPoint(guideObj.transform.position);
            var selfCanvas = guideObj.AddComponent<Canvas>();
            // 调整层级
            Debug.Log($"ViewPos{pos}");
            selfCanvas.overrideSorting = true;
            selfCanvas.sortingLayerName = canvasBlackMask.sortingLayerName;
            selfCanvas.sortingOrder = canvasBlackMask.sortingOrder + 1;
            this.StartTimer(delegate { selfCanvas.overrideSorting = true; });
            guideObj.AddComponent<GraphicRaycaster>();
            // 播放黑色遮罩动画
            Material mat = canvasBlackMask.transform.Find("Image").GetComponent<Image>().material;
            mat.SetFloat("_TargetPointX", pos.x);
            mat.SetFloat("_TargetPointY", pos.y);
            mat.SetFloat("_Threshold", 0);
            DOTween.To(() => 0, x => { mat.SetFloat("_Threshold", x); }, 0.7f, shadowAnimDuration).OnComplete(delegate
            {
                // 修改引导手的位置和层级并显示
                transGuideHand.gameObject.SetActive(true);
                transGuideHand.anchoredPosition = canvasBlackMask.GetComponent<RectTransform>().sizeDelta * pos;
                var canvasGuideHand = transGuideHand.GetComponent<Canvas>();
                canvasGuideHand.overrideSorting = true;
                canvasGuideHand.sortingLayerName = canvasBlackMask.sortingLayerName;
                canvasGuideHand.sortingOrder = canvasBlackMask.sortingOrder + 2;
            });
        }

        /// 重置UI对象的层
        public void StopGuide(GameObject guideObj)
        {
            canvasBlackMask.gameObject.SetActive(false);
            canvasBlackMask.transform.Find("GuideHand").gameObject.SetActive(false);
            if (guideObj.TryGetComponent(out GraphicRaycaster graphicRaycaster))
                Destroy(graphicRaycaster);
            if (guideObj.TryGetComponent(out Canvas canvas))
                Destroy(canvas);
        }
    }
}